package com.pai4j.message.subscription;

import com.pai4j.message.model.MessageContext;
import com.pai4j.message.model.SubscriptionConfig;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.stereotype.Component;

import jakarta.annotation.PostConstruct;
import java.util.ArrayList;
import java.util.List;

/**
 * 订阅管理器
 * 统一管理订阅相关功能
 *
 * @author PAI4J Team
 * @date 2025-11-01
 */
@Slf4j
@Component
@RequiredArgsConstructor
@ConditionalOnBean(MessageSubscription.class)
public class SubscriptionManager {

    private final MessageSubscription messageSubscription;

    /**
     * 订阅规则列表
     */
    private final List<SubscriptionRule> rules = new ArrayList<>();

    @PostConstruct
    public void init() {
        // 初始化默认规则
        rules.add(SubscriptionRule.createMessageTypeRule());
        rules.add(SubscriptionRule.createResourceRule());
        rules.add(SubscriptionRule.createUserRule());

        log.info("SubscriptionManager 初始化完成，规则数量: {}", rules.size());
    }

    /**
     * 用户订阅消息类型
     *
     * @param userId      用户ID
     * @param messageType 消息类型
     * @return 订阅ID
     */
    public String subscribeMessageType(String userId, String messageType) {
        SubscriptionConfig config = SubscriptionConfig.builder()
                .userId(userId)
                .subscriptionType("message_type")
                .enabled(true)
                .build();

        config.getMessageTypes().add(messageType);

        return messageSubscription.subscribe(config);
    }

    /**
     * 用户订阅资源
     *
     * @param userId     用户ID
     * @param resourceId 资源ID
     * @return 订阅ID
     */
    public String subscribeResource(String userId, String resourceId) {
        SubscriptionConfig config = SubscriptionConfig.builder()
                .userId(userId)
                .subscriptionType("resource")
                .enabled(true)
                .build();

        config.getResourceIds().add(resourceId);

        return messageSubscription.subscribe(config);
    }

    /**
     * 用户订阅另一个用户的动态
     *
     * @param userId       用户ID
     * @param targetUserId 目标用户ID
     * @return 订阅ID
     */
    public String subscribeUser(String userId, String targetUserId) {
        SubscriptionConfig config = SubscriptionConfig.builder()
                .userId(userId)
                .subscriptionType("user")
                .enabled(true)
                .build();

        config.getSubscribedUserIds().add(targetUserId);

        return messageSubscription.subscribe(config);
    }

    /**
     * 取消订阅
     *
     * @param subscriptionId 订阅ID
     */
    public void unsubscribe(String subscriptionId) {
        messageSubscription.unsubscribe(subscriptionId);
    }

    /**
     * 获取用户的所有订阅
     *
     * @param userId 用户ID
     * @return 订阅配置列表
     */
    public List<SubscriptionConfig> getUserSubscriptions(String userId) {
        return messageSubscription.getUserSubscriptions(userId);
    }

    /**
     * 检查用户是否订阅了该消息
     *
     * @param userId  用户ID
     * @param context 消息上下文
     * @return 是否订阅
     */
    public boolean isSubscribed(String userId, MessageContext context) {
        return messageSubscription.isSubscribed(userId, context);
    }

    /**
     * 通知订阅者
     *
     * @param context 消息上下文
     */
    public void notifySubscribers(MessageContext context) {
        messageSubscription.notifySubscribers(context);
    }

    /**
     * 获取订阅者列表
     *
     * @param context 消息上下文
     * @return 订阅者用户ID列表
     */
    public List<String> getSubscribers(MessageContext context) {
        return messageSubscription.getSubscribers(context);
    }

    /**
     * 添加订阅规则
     *
     * @param rule 规则
     */
    public void addRule(SubscriptionRule rule) {
        if (rule != null) {
            rules.add(rule);
            log.info("添加订阅规则: name={}, priority={}", rule.getRuleName(), rule.getPriority());
        }
    }

    /**
     * 获取所有规则
     *
     * @return 规则列表
     */
    public List<SubscriptionRule> getRules() {
        return new ArrayList<>(rules);
    }
}

